package com.atguigu.bigdata.scala.chapter05

object Scala06_Function_Nightmare {

    def main(args: Array[String]): Unit = {

        // TODO 函数式编程 - 噩梦
        // Scala函数式编程中有一个重要的原则：TODO 至简原则
        // 这里的简表示简单，简洁，函数式编程时能省则省
        // 完整函数 => 简化
        // 简化函数 => 完整
        def test(): String = {
            return "zhangsan"
        }

        //val s = test()
        //val s = test
        //println(s)

        // 1. 如果函数明确有返回值，那么函数体中的return关键字可以省略的
        //    满足条件的最后一行代码的执行结果为表达式的返回值
        def test1(): String = {
            "zhangsan"
        }

        // 2. 如果能够通过返回值推断出函数的返回值类型，那么返回值类型可以省略
        //    以后写函数时，尽量不要写返回值类型，最好由编译器自动推断
        //    但是在某些时候(多态)，不能省略
        //val name : Object = "zhangsan"

        def test2() = {
            val age = 30
            if ( age < 16 ) {
                "zhangsan"
            } else {
                null
            }
        }

        // 3. 如果参数列表中没有参数，那么声明时，小括号可以省略
        def test3: Unit = {
            println("zhangsan")
        }

        //test3() // 如果函数没有声明参数列表，那么调用函数时，为了统一，也不能增加参数列表的小括号
        //test3

        // 4. 如果函数的逻辑代码只有一行，那么大括号可以省略的
        def test4(): Unit = println("zhangsan")

        //test4()

        // 5. 融合上面的4种简化情况
//        def test5(): String = {
//            return "zhangsan"
//        }
//        def test5(): String = {
//            "zhangsan"
//        }
//        def test5() = {
//            "zhangsan"
//        }
//        def test5 = {
//            "zhangsan"
//        }
        // scala种函数和变量必须通过关键字来区分
        def test5 = "zhangsan"
        val test55 = "lisi"
        //println(test5)
        //println(test55)

        // 6. 将Unit和等号同时省略，函数没有返回值
        // 如果一个函数明确没有返回值，那么函数体中有return不起作用
        // 如果省略返回值类型，那么函数体中有return就会发生错误
        // 希望Unit返回值类型可以省略，而且同时函数体中也不用返回结果，这个时候就可以将Unit和等号同时省略
        // 在这种场景中，return仅仅起到了改变流程的作用
        def test6() {
            return "zhangsan"
        }

        //println(test6())

        // 7. 如果只关心函数的逻辑，而不关心函数的名称时，函数的名称和关键字也可以省略
//         当关键字和函数名省略后，返回值也需要同时省略
//         还需要将等号改为颜文字： =>
//         如果函数声明时没有名字和关键字，那么这个函数称之为匿名函数
        //    b(x:Int, y:Int) => x + y
        //    a(x:Int, y:Int) => x * y
//        def test7():Unit = {
//            println("test7...")
//        }
//        () => {
//            println("test7...")
//        }
        // 大括号可以理解为代码块
        // 小括号表示Unit，没有值

        //test7()

        // 匿名函数是不能直接调用的，如果想要调用，那么需要将函数赋值给变量使用
        val f = () => {
                println("test77...")
            }

        // 此时，变量就是一个函数，所以这个变量就可以调用了。
        f()


    }
}
